/********************************************
* Copyrigt (C) rumi
* Module: Serv_ComService.c
* V1.0.1
*********************************************/
#include "Serv_ComService.h"
#include <string.h>


/********************************************/
bool ComService_Send(ComService_TxDevice_Typedef *ComDevice,TansBuffer_Typedef *Sendbuffer)
{
    bool lbRet = false;
    bool lbOut = true;
    static uint8_t TmpSendBuff[64];
    static uint8_t SendCount=0;
    static uint8_t SendLength;
    ComService_TxDevice_Typedef *lDevice = ComDevice;
    COM_SEND_STATE_ENUM Send_State = E_COMSENSENDSTATE_INIT;
    SendLength = Sendbuffer->DataLen;

    while(lbOut)
    {
        switch(Send_State)
        {
            case E_COMSENSENDSTATE_INIT:
            {    
                SendCount = 0;
                Send_State = E_COMSENSENDSTAT_FRAMEHEAD;      
                break;
            }

            case E_COMSENSENDSTAT_FRAMEHEAD:
            {
                switch (Sendbuffer->FrameHead)
                {
                    case E_COMFRAMEHEAD_NORMAL:
                    {
                        TmpSendBuff[SendCount++]=0xBB;
                        TmpSendBuff[SendCount++]=0xA5;
                        TmpSendBuff[SendCount++]=SendLength;                      
                        break;
                    }
                    default:
                        break; 
                }
                Send_State = E_COMSENSENDSTAT_DATA;                          
                break;
            }
            
            case E_COMSENSENDSTAT_DATA:
            {
                //memcpy(&TmpSendBuff[SendCount],Sendbuffer->Buffer, Sendbuffer->DataLen);
                for (uint8_t i = 0; i < SendLength; i++)
                {
                    TmpSendBuff[SendCount++] = Sendbuffer->Buffer[i];
                }
                Send_State = E_COMSENSENDSTAT_FRAMEEND;               
                break;
            }

            case E_COMSENSENDSTAT_FRAMEEND:
            {
                switch (Sendbuffer->FrameTail)
                {
                    case E_COMFRAMETAIL_NONE:
                    {
                        break;
                    }
                    case E_COMFRAMETAIL_JustFloat:
                    {
                        TmpSendBuff[SendCount++] = 0x00;
                        TmpSendBuff[SendCount++] = 0x00;
                        TmpSendBuff[SendCount++] = 0x80;
                        TmpSendBuff[SendCount++] = 0x7F;
                        break;
                    }
                    default:
                        break; 
                }
                Send_State = E_COMSENSENDSTAT_SEND;          
                break;
            }

            case E_COMSENSENDSTAT_SEND:
            {
                switch(lDevice->Dev_Type)
                {
                    case E_COMSERVICE_UART:
                    {
                        //lbRet = BSP_Uart_DMA_Send(lDevice->ComDevice,SendCount,TmpSendBuff);
                        break;
                    }
                    case E_COMSERVICE_CAN:
                    {
                        
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
                lbOut = false; 
                break;
            }

            default:
            {
                lbOut = false;
                break;
            }
        }
    }
    return lbRet;
}
/********************************************/
uint8_t *ComService_Rx_Handle(CBuff *Recive_CBuff)
{
    // Attention: must run in 5ms !!! because over time
    static COM_FRAME_HEAD_ENUM seHeadType;
    static COM_FRAME_CRC_ENUM seCRCType;
    static uint8_t sucLength,sucOverTime;
    static uint16_t u16CRC_Sum=0,u16CRC_Calc=0;
	static uint8_t Cbuff_Len;
    static uint8_t sucReciveData[64];
    CBuff *lRecive_CBuff = Recive_CBuff;
       
    for(;;)
    {
        Cbuff_Len = CBuff_GetLength(lRecive_CBuff);
        if(Cbuff_Len < 6)
        {
            return NULL;
        }
        CBuff_Read(lRecive_CBuff,sucReciveData,4);
        if(sucReciveData[0] != 0xAA){
            CBuff_Pop(lRecive_CBuff,sucReciveData,1);	// if not 0xAA Delete the first data
		    continue;
        }else{
            break;
        }
    }
    if(sucReciveData[0] == 0xAA)
    {
        seHeadType = E_COMFRAMEHEAD_NONE;   // must have one frame head
        seCRCType = E_COMFRAMETAIL_NONE;
        sucLength = 0;
        switch(sucReciveData[1])
        {
            case 0xA0:seHeadType = E_COMFRAMEHEAD_NORMAL;seCRCType = E_COMFRAMETAIL_NONE; break;
            case 0xA5:seHeadType = E_COMFRAMEHEAD_NORMAL;seCRCType = E_COMFRAMETAIL_CRC16;break;
            case 0xB0:seHeadType = E_COMFRAMEHEAD_UPDATE;seCRCType = E_COMFRAMETAIL_NONE; break;          
            case 0xB5:seHeadType = E_COMFRAMEHEAD_UPDATE;seCRCType = E_COMFRAMETAIL_CRC16;break;
            default:break;
        }
        if(seHeadType == E_COMFRAMEHEAD_NONE)
        {
            CBuff_Pop(lRecive_CBuff,sucReciveData,1);
            return NULL;
        }
        sucLength = sucReciveData[2]+5;
        if (sucLength > 64)
        {		
            CBuff_Pop(lRecive_CBuff,sucReciveData,2); 	// detect if the length over the range
            return NULL;
        }
        else if(CBuff_GetLength(lRecive_CBuff) < sucLength)
        {
            sucOverTime++;
            if(sucOverTime >= 20)   // 5ms*20 = 100ms
            {
                sucOverTime = 0;
                CBuff_Pop(lRecive_CBuff,sucReciveData,2);				// 100ms don't receive the rest of the data, remove header and return
            }
            return NULL;
        }
        else
        {
            sucOverTime = 0;
            CBuff_Read(lRecive_CBuff,sucReciveData,sucLength);			// Pull out all the data
            switch(seCRCType)
            {
                case E_COMFRAMETAIL_NONE:
                {
                    u16CRC_Calc = 0xfe*256+0xfe;
                    u16CRC_Sum = sucReciveData[sucLength-2]*256 + sucReciveData[sucLength-1];
                    break;
                }
                case E_COMFRAMETAIL_CRC16:
                {
                    u16CRC_Calc = CRC16_Check_Code(sucReciveData+3,(sucLength-5));
                    u16CRC_Sum = sucReciveData[sucLength-2]*256 + sucReciveData[sucLength-1];
                    break;
                }
                default:break;
            }
            	
            if(u16CRC_Calc != u16CRC_Sum)
            {
                CBuff_Pop(lRecive_CBuff,sucReciveData,2); 					// CRC error,Delete the head
            }
            else
            {
                CBuff_Pop(lRecive_CBuff,sucReciveData,sucLength);
                sucReciveData[0] = seHeadType;
                return sucReciveData;                   
            }
        }
    }
    return NULL;
}

/********************************************
 * End of file
*********************************************/
